package com.project.fortuneteller.service.impl;

import cn.hutool.crypto.digest.BCrypt;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.smartjavaai.common.entity.face.FaceSearchResult;
import com.auth0.jwt.interfaces.Claim;
import com.project.fortuneteller.common.Constants;
import com.project.fortuneteller.config.RedisConstant;
import com.project.fortuneteller.pojo.UserInfo;
import com.project.fortuneteller.pojo.dto.FindNewFriendDto;
import com.project.fortuneteller.pojo.vo.*;
import com.project.fortuneteller.mappers.UserMapper;
import com.project.fortuneteller.pojo.User;
import com.project.fortuneteller.service.FaceCheckService;
import com.project.fortuneteller.service.UserService;
import com.project.fortuneteller.utils.FaceRecUtils;
import com.project.fortuneteller.utils.JwtUtil;
import com.project.fortuneteller.utils.Result;
import com.project.fortuneteller.utils.ThreeCache;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author 16905
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Resource
    public UserMapper userMapper;

    @Value("${jiliason.profile}")
    private String PIC_PATH;

    @Resource
    private UserService userService;

    @Resource
    private RedissonClient redissonClient;

    @Resource
    private FaceCheckService faceCheckService;

    /**
     * 通过用户名模糊匹配
     *          用户信息
     * @return
     */
    public Result getLikeByUserNickName(String tokenVal,String nickStr){

        log.info("tokenVal to userId:{}",ThreeCache.get(tokenVal));
        // 用token的值 获取 userId
        User userDetails = userMapper.getById((Integer) ThreeCache.get(tokenVal));

        if(userDetails==null){
            return Result.error("用户不存在");
        }

        // 通过数据库的查找
        List<User> byUsername = userMapper.getByUsername('%'+ nickStr + '%');
        // 使用
        List<FindNewFriendDto> list = new ArrayList<>();
        // 去除与发出请求的用户信息昵称相同的用户
      if(!byUsername.isEmpty()) {
          // 删除
          byUsername.removeIf(user -> user.getUserName().equals(userDetails.getUserName()));
          for (User user : byUsername) {
              FindNewFriendDto findNewFriendDto = new FindNewFriendDto();
              BeanUtils.copyProperties(user, findNewFriendDto);
              findNewFriendDto.setUserId(user.getId());
              list.add(findNewFriendDto);
          }
      }
        return Result.success(list);
    }

    /**
     * @param userVo
     * @return
     */
    @Override
    public Result login(UserLoginVO userVo, String tokenVal) {
        // 参数非空校验
        if (userVo == null) {
            return Result.error("用户信息不能为空");
        }
        if (userVo.getEmail() == null || userVo.getEmail().trim().isEmpty()) {
            return Result.error("邮箱不能为空");
        }
        if (userVo.getPassword() == null || userVo.getPassword().trim().isEmpty()) {
            return Result.error("密码不能为空");
        }

        // 获取个人信息
        User userInfo = userMapper.getByEmail(userVo.getEmail());
        if (userInfo == null) {
            log.info("登录错误，用户不存在: {}", userVo.getEmail());
            return Result.error("登录错误，用户不存在");
        }

        try {
            // 密码校验
            if (!BCrypt.checkpw(userVo.getPassword(), userInfo.getPassword())) {
                log.info("登录错误，密码错误: {}", userVo.getEmail());
                return Result.error("密码错误");
            }
        } catch (Exception e) {
            log.error("密码校验异常: {}", e.getMessage(), e);
            return Result.error("登录失败，系统异常");
        }

        return this.loginByUserInfo(userInfo);
    }


     /**
      *
      * 登录操作完成后 存储用户信息的处理
      * */
    public Result loginByUserInfo(User user){
        UserLoginVO userLoginDTO = new UserLoginVO();
        BeanUtils.copyProperties( user, userLoginDTO );
        // 密码 判断 成功 ，密码正确
        // 获取token 生成一个token
        String token = JwtUtil.createToken(userLoginDTO);
        // 存储到缓存当中  token <-> id
        //  获取 用户 ID
        int userId =  userLoginDTO.getId();
        // 更新 token的 操作
        // 判断 是否 包含 userId

        // 把 userId 放在 token 的键值对里面
        UserInfo userInfo = UserInfo.builder().email(user.getEmail())
                .id(user.getId().toString())
                .token(token)
                .build();
        RBucket<UserInfo> bucket = redissonClient.getBucket(token);
        log.info( "token: " + token );
        // 设置 redis 的过期时间
        bucket.set(userInfo, RedisConstant.USER_LOGIN_EXPIRE_TIME, TimeUnit.SECONDS);

        if(ThreeCache.userMap.containsKey(userId)){
            // 更新token
            String key = ThreeCache.userMap.get(userId);
            ThreeCache.remove(key);
        }
        /**
         *  获取
         */
        ThreeCache.userMap.put(userId,token);
        // token -- userId
        ThreeCache.put(token,userId);
        // 成功 获取 token 值
        return Result.success(token);

    }

    /**
     * 使用 3DES进行对称加密
     * @param userVo
     * @return
     */
    @Override
    public Result register(UserLoginVO userVo) {
        // 参数非空校验
        if (userVo == null) {
            return Result.error("用户信息不能为空");
        }
        if (userVo.getEmail() == null || userVo.getEmail().trim().isEmpty()) {
            return Result.error("邮箱不能为空");
        }
        if (userVo.getPassword() == null || userVo.getPassword().trim().isEmpty()) {
            return Result.error("密码不能为空");
        }

        // 邮箱格式校验
        if (!userVo.getEmail().matches(Constants.EMAIL_REGEX)) {
            return Result.error("邮箱格式不正确");
        }

        // 密码强度校验
        if (userVo.getPassword().length() < Constants.MIN_PASSWORD_LENGTH) {
            return Result.error("密码长度不能少于" + Constants.MIN_PASSWORD_LENGTH + "位");
        }

        // 查看用户是否已存在
        User existingUser = userMapper.getByEmail(userVo.getEmail());
        if (existingUser != null) {
            return Result.error("用户已经存在");
        }

        try {
            // 对密码进行加密
            String password = userVo.getPassword();
            String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt());
            log.info("用户密码加密成功");

            userVo.setPassword(hashedPassword);
            User user = new User();
            BeanUtils.copyProperties(userVo, user);

            // 插入用户信息
          userMapper.insert(user);

        } catch (Exception e) {
            log.error("用户注册异常: {}", e.getMessage(), e);
            return Result.error("用户注册失败，系统异常");
        }
        return null;
    }
    /**
     *
     * @param userDto
     * @return
     */
    @Override
    public Result checkLogin(UserLoginVO userDto) {
        // 密码校验
        Map<String, Claim> stringClaimMap = JwtUtil.verifyToken(userDto.getToken());
        if(stringClaimMap==null){
            return Result.error("校验失败,为空");
        }
        log.info("校验 ClaimMap:  {}", stringClaimMap);
        return Result.success("校验成功");
    }

    @Override
    public Result loginFace(LoginFaceVO loginFaceVO) {
        if (loginFaceVO == null) {
            return Result.error("登录信息不能为空");
        }

        if (loginFaceVO.getBase64String() == null || loginFaceVO.getBase64String().trim().isEmpty()) {
            return Result.error("图片数据不能为空");
        }

        String metadata = faceCheckService.loginFace(loginFaceVO);

        if (metadata == null) {
            return Result.error("用户未进行人脸信息维护");
        }
        JSONObject entries = JSONUtil.parseObj(metadata);
        String userId = (String) entries.get("userid");
        User userInfo = userMapper.getById(Integer.parseInt(userId));
        if (userInfo == null) {
            return Result.error("用户不存在");
        }
        return  this.loginByUserInfo(userInfo);
        // 返回token
    }

    /**
     * 登出  登录逻辑从缓存中移除 token 和 userid
     * @param
     * @return
     */

    @Override
    public Result logout(String token) {
        // 参数非空校验
        if (token == null || token.trim().isEmpty()) {
            return Result.error("Token不能为空");
        }

        try {
            // 移除用户缓存
            ThreeCache.remove(token);
            log.info("用户登出成功，当前缓存大小: {}", ThreeCache.size());

            return Result.success("用户登出成功");
        } catch (Exception e) {
            log.error("用户登出异常: {}", e.getMessage(), e);
            return Result.error("登出失败，系统异常");
        }
    }


    /**
     * 编辑个人信息
     * @param userEditorVo
     * @return
     */
     @Override
    public Result editorAndSave(UserEditorVo userEditorVo) {
        // 通过
        Integer userId = (Integer)ThreeCache
                .get(userEditorVo.getToken());

        log.info("获取的值: {}", userId);
         User user = new User();
         user.setId(userId);
         BeanUtils.copyProperties(userEditorVo,user);
         int res = userMapper.editorInsert(user);
         if(res==1){
             return Result.success( "编辑成功 !!!");
         }else{
             return Result.success("用户信息修改失败 !!!");
         }

    }

    /**
     * 获取 用户 信息
     * @param token
     * @return
     */
    @Override
    public Result getUserInfo(String token) {
        // 参数非空校验
        if (token == null || token.trim().isEmpty()) {
            return Result.error("Token不能为空");
        }

        try {
            log.info("获取用户信息，当前缓存大小: {}", ThreeCache.size());

            // 从缓存中获取用户ID
            Object userIdObj = ThreeCache.get(token);
            if (userIdObj == null) {
                return Result.error("Token无效或已过期");
            }

            String id = userIdObj.toString();
            User user = userMapper.getById(Integer.parseInt(id));

            if (user == null) {
                return Result.error("用户不存在");
            }

            return Result.success(user);
        } catch (NumberFormatException e) {
            log.error("用户ID格式错误: {}", e.getMessage(), e);
            return Result.error("用户ID格式错误");
        } catch (Exception e) {
            log.error("获取用户信息异常: {}", e.getMessage(), e);
            return Result.error("获取用户信息失败，系统异常");
        }
    }

    /**
     * 获取 当前在线人数
     * @return
     */

    public Result getCurrentUserCount(){
        return Result.success(ThreeCache.size());
    }

    @Override
    public Result imageLoadAndRegisterFace(RegisterFaceVO registerFaceVO) {
        // 参数非空校验
        if (registerFaceVO == null) {
            return Result.error("注册信息不能为空");
        }
        if (registerFaceVO.getUserId() == null || registerFaceVO.getUserId().trim().isEmpty()) {
            return Result.error("用户ID不能为空");
        }
        if (registerFaceVO.getRoleId() == null || registerFaceVO.getRoleId().trim().isEmpty()) {
            return Result.error("角色ID不能为空");
        }
        if (registerFaceVO.getBase64String() == null || registerFaceVO.getBase64String().trim().isEmpty()) {
            return Result.error("图片数据不能为空");
        }

        try {
            String base64String = registerFaceVO.getBase64String();
            String base64Data = base64String;

            // 去除Base64字符串中的前缀
            if (base64String.contains(",")) {
                base64Data = base64String.substring(base64String.indexOf(",") + 1);
            }

            // 解码Base64字符串
            byte[] imageBytes = Base64.getDecoder().decode(base64Data);

            // 将字节数组转换为BufferedImage
            try (ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes)) {
                BufferedImage image = ImageIO.read(bis);
                if (image == null) {
                    return Result.error("图片格式不正确");
                }

                String result = FaceRecUtils.registerFace(image, registerFaceVO.getUserId(), registerFaceVO.getRoleId());
                if (result == null) {
                    return Result.error("人脸注册失败");
                }

                return Result.success(result);
            }
        } catch (IllegalArgumentException e) {
            log.error("Base64解码失败: {}", e.getMessage(), e);
            return Result.error("图片数据格式错误");
        } catch (IOException e) {
            log.error("图片处理异常: {}", e.getMessage(), e);
            return Result.error("图片处理失败");
        } catch (Exception e) {
            log.error("人脸注册异常: {}", e.getMessage(), e);
            return Result.error("人脸注册失败，系统异常");
        }
    }

}
